#usr/bin/python

import math

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from PyQt4 import QtGui, QtOpenGL, QtCore
from PyQt4.QtCore import Qt
import math


class canvas_GL (QtOpenGL.QGLWidget):
	"""Canvas GL plotting in 3 dimensions spectra"""
	
	def __init__(self, spl, peak =None, parent = None): #, mapped_peaks
		"""Constructor, initialization"""
		
		QtOpenGL.QGLWidget.__init__(self,parent)
		self.setMinimumSize(500,300)
		#self.grabKeyboard()
		self.setEnabled(True)
		self.spl = spl
		self.peak =peak
		#self.mapped_peaks = mapped_peaks
		
		self.axes = 0
		self.data = 0
		#
		self.lastpos = QtCore.QPoint()
		
		self.corner_=100.0
		self.near_=0.0
		self.far_=600.0
		self.zoom_= 1.5
		self.xrot_=220
		self.yrot_ = 220
		self.zrot_=0
		self.trans_x_ =0.0
		self.trans_y_ = 0.0
		
		self.massList=[]
		self.intensityList=[]
		self.rtList=[]
		self.max_value = self.get_max_value()
		self.max_rt =self.get_max_rt()
		self.max_mass =self.get_max_mass()
		#i =0.
		#self.parent().parent().statusBar().showMessage("Data Drawing", 1000)
		for spectr in self.spl.getSpectra():
			self.massList.append(self.data_normalization(spectr.mass, 2*self.corner_))# )
			self.intensityList.append(self.data_normalization1(spectr.intens, self.max_value, self.far_ -self.near_ -4*self.corner_ ))
			self.rtList.append(spectr.t_max)
			self.norm_rt = self.data_normalization(self.rtList,2*self.corner_)
			#i+=(1./(float(len(self.spl.getSpectra()))))*100
			#self.parent().parent().pb.setValue(i)
			
	def get_max_value(self):
		"""return max value of a dataset"""
		
		maxi=[]
		for spectr in self.spl.getSpectra():
			maxi.append(max(spectr.intens))
		return max(maxi)
	
	
	def get_max_rt(self):
		maxi=[]
		for spectr in self.spl.getSpectra():
			maxi.append(spectr.t_max)
		return max(maxi)
	
	def get_max_mass(self):
		maxi=[]
		for spectr in self.spl.getSpectra():
			maxi.append(max(spectr.mass))
		return max(maxi)
		
	def data_normalization1(self,data_list, maxi, value):
		""" normalize data """
		
		new_data =[]
		for x in data_list:
			if x == maxi:
				new_data.append(value)
			else:
				new_data.append((x*value)/maxi)
		return new_data
		
	def data_normalization(self,data_list, value):
		maxi =max(data_list)
		new_data =[]
		for x in data_list:
			if x == maxi:
				new_data.append(value)
			else:
				new_data.append((x*value)/maxi)
		return new_data
				
	def resizeGL(self, w, h):
		"""called when window is being resized"""
		
		width_ = float(w)
		heigth_ = float(h)
		glViewport(0,0, w, h)	 
		glMatrixMode(GL_PROJECTION)
		glLoadIdentity()
		glOrtho(-self.corner_*self.zoom_, self.corner_*self.zoom_,	-self.corner_*self.zoom_, self.corner_*self.zoom_ , self.near_, self.far_)
		glMatrixMode(GL_MODELVIEW)
	
	def initializeGL(self):
		"""needed """
		glClearColor(1.,1.,1.,1.)
		glEnable(GL_DEPTH_TEST)
		glEnable(GL_BLEND)
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
		#glMatrixMode(GL_MODELVIEW)
		#glLoadIdentity()
		#gluLookAt(0,0,100,\
		#			0,0,0,\
		#			0,0,0)
		self.axes = self.makeAxes()
		self.data = self.makeDataAsStick()
		self.drawAxisLegend()

	def paintGL(self):
		"""needed, called each time glDraw"""
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
		glLoadIdentity()
	
		glTranslated(0.0, 0.0,-3.0*self.corner_)
		glRotated(self.xrot_ / 16.0, 1.0, 0.0, 0.0)
		glRotated(self.yrot_ / 16.0, 0.0, 1.0, 0.0)
		glRotated(self.zrot_/16.0, 0.0, 0.0, 1.0)
		glTranslated(self.trans_x_, self.trans_y_, 3.0*self.corner_)
		
		glEnable(GL_DEPTH_TEST)
		glEnable(GL_BLEND)
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
		
		glCallList(self.axes)
		glCallList(self.data)
		self.drawAxisLegend()

	
	def makeAxes(self):
		"""Draw Axes """
		lspectr = glGenLists(1)
		glNewList(lspectr,GL_COMPILE)
		glLineWidth(3.0)
		glShadeModel(GL_FLAT)
		glBegin(GL_LINES)
		glColor(0.,0.,1.)
		#x_achse
		glVertex3d(-self.corner_, -self.corner_, -self.near_-2*self.corner_)
		glVertex3d( self.corner_, -self.corner_, -self.near_-2*self.corner_)
		#z-achse
		glVertex3d(-self.corner_, -self.corner_, -self.near_-2*self.corner_)
		glVertex3d( -self.corner_, -self.corner_, -self.far_+2*self.corner_)
		#y-achse
		glVertex3d(-self.corner_, -self.corner_, -self.near_-2*self.corner_)
		glVertex3d( -self.corner_, self.corner_, -self.near_-2*self.corner_)
		
		glEnd()
		glEndList()
		
		return lspectr
	
	
	def makeDataAsStick(self):
		""" Draw Data """
		lspectr  = glGenLists(1)
		glNewList(lspectr,GL_COMPILE)
		glLineWidth(1.)
		glShadeModel(GL_FLAT)
		for i, mass_of_spectrum in enumerate(self.massList):
			for j, mass in enumerate(mass_of_spectrum):
				glBegin(GL_LINES)
				if self.peak:
					if mass == (self.peak.get_trans_prec()* 2*self.corner_)/self.max_mass:
						if self.norm_rt[i] > (self.peak.get_rt_min()*2*self.corner_)/self.max_rt and \
								self.norm_rt[i] < (self.peak.get_rt_max()*2*self.corner_)/self.max_rt:
							glColor(1., 0., 0.)
						else:
							glColor(0., 0., 1.)
				glVertex3f( - self.corner_ +  mass, -self.corner_, - self.near_- 2*self.corner_ - self.norm_rt[i])
				glVertex3f( - self.corner_ + mass, - self.corner_ + self.intensityList[i][j], - self.near_- 2*self.corner_ - self.norm_rt[i])	
				glEnd()
		"""
		Test drawing area
		"""
		glEndList()
		return lspectr
	
	def drawAxisLegend(self):
		
		"""Draw Axis Legend"""
		
		font =QtGui.QFont("Typewriter")
		font.setPixelSize(10)
				
		#RT axis legend
		font.setPixelSize(12)
		self.qglColor(Qt.black)
		mz_label = "m/z";rt_label = "retention time [s]"
		self.renderText(0.0,  -self.corner_-20.0,  -self.near_-2*self.corner_+20.0, rt_label, font)
		self.renderText(-self.corner_-20.0, -self.corner_-20.0, -self.near_-3*self.corner_, mz_label, font)
		self.renderText(-self.corner_-20.0, self.corner_+10.0, -self.near_-2*self.corner_+20.0, "intensity %", font)
		font.setPixelSize(10)
		
		#for rt number
		i=30
		while i < self.corner_:
			text = str(self.rtList[i])
			self.renderText(-self.corner_+self.norm_rt[i], -self.corner_-5.0, -self.near_-2*self.corner_+15.0, text, font);
			i+=50
		#for mz number
		
	def resetTranslations(self):
		
		"""reset the different translation to 0"""
		
		self.trans_x_ =0.
		self.trans_y_ =0.
	
	def normalizeAngle(self,angle):
		while (angle < 0):
			angle += 360 * 16
		while (angle > 360 * 16):
			angle -= 360 * 16
			
	
	########MOUSE AND KEYBOARDS EVENTS#########
	def wheelEvent(self, event):
		if event.delta() >0:
			self.zoom_ -= .05
			
		else:
			self.zoom_ += .05
		glMatrixMode(GL_PROJECTION)
		glLoadIdentity()
		glOrtho(-self.corner_*self.zoom_, self.corner_*self.zoom_,	-self.corner_*self.zoom_, self.corner_*self.zoom_ , self.near_, self.far_)
		glMatrixMode(GL_MODELVIEW)
		self.glDraw()
		event.accept()
		
	def keyPressEvent(self,  event):
		if event.key() == Qt.Key_Plus:
			self.zoom_ -= .1
			glMatrixMode(GL_PROJECTION)
			glLoadIdentity()
			glOrtho(-self.corner_*self.zoom_, self.corner_*self.zoom_,	-self.corner_*self.zoom_, self.corner_*self.zoom_ , self.near_, self.far_)
			glMatrixMode(GL_MODELVIEW)

		if event.key() == Qt.Key_Minus:
			self.zoom_ += .1
			glMatrixMode(GL_PROJECTION) #// You had GL_MODELVIEW
			glLoadIdentity()
			glOrtho(-self.corner_*self.zoom_, self.corner_*self.zoom_,	-self.corner_*self.zoom_, self.corner_*self.zoom_ , self.near_, self.far_)
			glMatrixMode(GL_MODELVIEW)
		if event.key() == Qt.Key_Up:
			self.trans_y_ +=10
		if event.key() == Qt.Key_Down:
			self.trans_y_ -=10
		if event.key() == Qt.Key_Left:
			self.trans_x_ -=10
		if event.key() == Qt.Key_Right:
			self.trans_x_ +=10
		self.glDraw()
		
	
	
	def mousePressEvent(self, event):
	   self.lastpos = QtCore.QPoint(event.pos())

	def mouseMoveEvent(self, event):
		dx = event.x() - self.lastpos.x()
		dy = event.y() - self.lastpos.y()
		
		if event.buttons() == QtCore.Qt.LeftButton:
			self.xrot_= self.xrot_ + 8 * dy
			self.yrot_=self.yrot_ + 8 * dx
		"""
		elif event.buttons() and QtCore.Qt.RightButton:
		   self.xrot_=self.xrot_ + 8 * dy
		   self.yrot_=self.zrot_ + 8 * dx
		"""
		if event.buttons()== QtCore.Qt.RightButton:
			self.setCursor(QtGui.QCursor(Qt.ClosedHandCursor))
			self.trans_y_ += dy
			self.trans_x_ -= dx
			
		self.lastpos = QtCore.QPoint(event.pos())
		self.glDraw()
	
	def mouseReleaseEvent(self, event):
		self.setCursor(QtGui.QCursor(Qt.ArrowCursor))
	
	def closeEvent(self, event):
		self.releaseKeyboard()
	
	
		

